package cn.changhong.user.util;

import cn.changhong.user.aop.ResultBean;
import cn.changhong.user.exception.ExpectedTokenException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import net.sf.json.JSONObject;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.PrintWriter;
import java.util.*;

/**
 * token 验证工具类
 *
 * @author itguang
 * @create 2018-01-06 15:01
 **/
public class TokenAuthenticationService {

    /**
     * 过期时间 2小时
     */
    static final long EXPIRATIONTIME = 1000 * 60 * 60 * 2 ;
    /**
     * JWT 密码
     */
    static final String SECRET = "yearcon";
    /**
     * TOKEN前缀
     */
    static final String TOKEN_PREFIX = "Bearer ";
    /**
     * 存放Token的Header Key
     */
    static final String HEADER_STRING = "token";

    /**
     * 自定义的 playload
     */
    static final String AUTHORITIES = "authorities";

    /**
     * 将jwt token 写入body
     *
     * @param response
     * @param authentication
     */
    public static void addAuthentication(HttpServletResponse response, Authentication authentication) {
        Collection list=authentication.getAuthorities();
        GrantedAuthorityImpl o=(GrantedAuthorityImpl)list.iterator().next();
        String token = Jwts.builder()
                .claim(AUTHORITIES,o.getAuthority())
                .setSubject(authentication.getName())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
        try {
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter out = response.getWriter();
            JSONObject jsonObject=JSONObject.fromObject(new ResultBean<String>(TOKEN_PREFIX+token));
            out.print(jsonObject.toString());
            out.flush();
            out.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 从请求头中解析出 Authentication
     * @param request
     * @return
     */
    public static Authentication getAuthentication(HttpServletRequest request) throws AuthenticationException{
        String token = request.getHeader(HEADER_STRING);
        if(token==null){
            throw new ExpectedTokenException();
        }
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(SECRET)
                    .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                    .getBody();
        }catch ( JwtException e){
            throw new CredentialsExpiredException("token is expired");
        }
        String username = claims.getSubject();
        List<GrantedAuthority> authorities =  AuthorityUtils.
                commaSeparatedStringToAuthorityList((String) claims.get(AUTHORITIES));
        if (username != null) {
            return new UsernamePasswordAuthenticationToken(username, null, authorities);
        }
        return null;
    }


}

